package JHfstools;


import JHfstools.hftmain.dlgdata;

import java.awt.EventQueue;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Rectangle;
import java.awt.Shape;
import org.apache.commons.net.ftp.FTPClient;
import org.apache.commons.net.ftp.FTPFile;

import javax.swing.JDialog;
import javax.swing.SpringLayout;
import java.awt.Color;
import javax.swing.JScrollPane;
import javax.swing.JEditorPane;
import java.awt.Font;

import javax.swing.AbstractAction;
import javax.swing.JButton;
import javax.swing.ImageIcon;
import javax.swing.JOptionPane;
import javax.swing.SwingConstants;
import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.ObjectInputStream;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.net.URL;
import java.awt.Dimension;
import javax.swing.JToolBar;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import javax.swing.event.UndoableEditEvent;
import javax.swing.event.UndoableEditListener;
import javax.swing.text.AbstractDocument;
import javax.swing.text.BadLocationException;
import javax.swing.text.DefaultHighlighter;
import javax.swing.text.Document;
import javax.swing.text.Highlighter;
import javax.swing.text.Highlighter.HighlightPainter;
import javax.swing.text.JTextComponent;
import javax.swing.text.LayeredHighlighter;
import javax.swing.text.Position;
import javax.swing.text.View;
import javax.swing.undo.CannotRedoException;
import javax.swing.undo.CannotUndoException;
import javax.swing.undo.UndoManager;
import javax.swing.undo.UndoableEdit;



public class hftedit extends JDialog implements UndoableEditListener {
	/**
	 * 
	 */

	private static JEditorPane hfteditpane;
	private JButton hfteditsave;
	private JButton hfteditselall;
	private JButton hfteditcopy;
	private JButton hfteditcut;
	private JButton hfteditpaste;
	private JButton hfteditredo;
	private JButton hfteditundo;
	private JButton hfteditcncl;
	DefaultHighlighter.DefaultHighlightPainter highlightPainter = 
	        new DefaultHighlighter.DefaultHighlightPainter(Color.CYAN);
	private JButton hfteditfind;
	TypingEdit lastEdit;
	Document doc;


	/**
	 * Launch the application.
	 */
	public static void main(String[] args) {
		EventQueue.invokeLater(new Runnable() {
			public void run() {
				try {
					hftedit dialog = new hftedit(null, null);
					dialog.setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE);
					dialog.setVisible(true);
				} catch (Exception e) {
					e.printStackTrace();
				}
			}
		});
	}
	UndoManager undo = new UndoManager();
	/**
	 * Create the dialog.
	 */
	public hftedit(final dlgdata d, final FTPClient f) {
		setPreferredSize(new Dimension(750, 800));
		setMinimumSize(new Dimension(750, 800));
		setSize(new Dimension(750, 800));
		setModal(true);
		getContentPane().setBackground(new Color(245, 255, 250));
		setTitle("HFS Tools Edit");
		if (d.getlogfl() == true){setTitle("HFS Tools log");}
		setBounds(100, 100, 645, 720);
		SpringLayout springLayout = new SpringLayout();
		getContentPane().setLayout(springLayout);
		
		scrollPane = new JScrollPane();
		scrollPane.setAutoscrolls(true);
		springLayout.putConstraint(SpringLayout.WEST, scrollPane, 10, SpringLayout.WEST, getContentPane());
		springLayout.putConstraint(SpringLayout.SOUTH, scrollPane, -10, SpringLayout.SOUTH, getContentPane());
		springLayout.putConstraint(SpringLayout.EAST, scrollPane, -5, SpringLayout.EAST, getContentPane());
		getContentPane().add(scrollPane);
		
		hfteditpane = new JEditorPane();
		hfteditpane.setFont(new Font("Verdana", Font.PLAIN, 14));
		scrollPane.setViewportView(hfteditpane);
		final WordSearcher searcher = new WordSearcher(hfteditpane);
		JToolBar toolBar = new JToolBar();
		springLayout.putConstraint(SpringLayout.NORTH, scrollPane, 6, SpringLayout.SOUTH, toolBar);
		springLayout.putConstraint(SpringLayout.NORTH, toolBar, 10, SpringLayout.NORTH, getContentPane());
		springLayout.putConstraint(SpringLayout.WEST, toolBar, 10, SpringLayout.WEST, getContentPane());
		springLayout.putConstraint(SpringLayout.SOUTH, toolBar, -689, SpringLayout.SOUTH, getContentPane());
		springLayout.putConstraint(SpringLayout.EAST, toolBar, -5, SpringLayout.EAST, getContentPane());
		getContentPane().add(toolBar);
		hfteditsave = new JButton("Save");
		hfteditsave.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				if (d.getfl() == "local"){// Its a local file
				      try
				      {   	  
				         FileWriter fileOut = new FileWriter(d.getsel());
				         hfteditpane.write(fileOut);
				         fileOut.close();
				      }catch(IOException i)
				      {
				    	  i.printStackTrace();
				      }

JOptionPane.showMessageDialog(hftedit.getJHFSeditpane(), "File "+d.getsel()+" saved.","HFS Tools",JOptionPane.INFORMATION_MESSAGE);
				}else{
					String os = hfteditpane.getText();
					String fn = d.getsel();
					FTPFile ftpf = new FTPFile();
					//FileOutputStream fo = (FileOutputStream) ftpf.getOutputStream();
					//BufferedWriter bw = new BufferedWriter (new OutputStreamWriter(fo));
					//JHFSeditpane.write(bw);
					//fo.write((int) ftpf.length());
				}
			}
			}
		);
		hfteditsave.setVerticalTextPosition(SwingConstants.BOTTOM);
		hfteditsave.setHorizontalTextPosition(SwingConstants.CENTER);
		hfteditsave.setToolTipText("Save file\r\n");
		hfteditsave.setIcon(new ImageIcon(hftedit.class.getResource("images/edit_save.png")));
		toolBar.add(hfteditsave);
		
		hfteditselall = new JButton("Select All");
		hfteditselall.setVerticalTextPosition(SwingConstants.BOTTOM);
		hfteditselall.setHorizontalTextPosition(SwingConstants.CENTER);
		hfteditselall.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				hfteditpane.selectAll();
				//JHFSeditpane.getSelectedText().length();
				try {
					hfteditpane.getHighlighter().addHighlight(0, hfteditpane.getSelectedText().length(), 
					        highlightPainter);
				} catch (BadLocationException e1) {
					e1.printStackTrace();
				}
			}
		});
		
		hfteditfind = new JButton("Find");
		hfteditfind.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent arg0) {
				hftfinder findit = new hftfinder();
				findit.pack();
				ActionListener finder = new findListener();
				hftfinder.getFindnxtbtn().addActionListener(finder);
				hftfinder.getFindprevbtn().addActionListener(finder);
				hftfinder.getFindallbtn().addActionListener(finder);
				hftfinder.getRepbtn().addActionListener(finder);
				hftfinder.getRepallbtn().addActionListener(finder);
				findit.setLocationRelativeTo(null);
				findit.setVisible(true);


			}
		});
		hfteditfind.setHorizontalTextPosition(SwingConstants.CENTER);
		hfteditfind.setHorizontalAlignment(SwingConstants.LEFT);
		hfteditfind.setVerticalTextPosition(SwingConstants.BOTTOM);
		hfteditfind.setToolTipText("Find and replace text");
		hfteditfind.setIcon(new ImageIcon(hftedit.class.getResource("images/edit_find.png")));
		toolBar.add(hfteditfind);

		hfteditselall.setToolTipText("Select all");
		hfteditselall.setIcon(new ImageIcon(hftedit.class.getResource("images/edit_select_all.png")));
		toolBar.add(hfteditselall);
		
		hfteditcopy = new JButton("Copy");
		hfteditcopy.setHorizontalTextPosition(SwingConstants.CENTER);
		hfteditcopy.setVerticalTextPosition(SwingConstants.BOTTOM);
		hfteditcopy.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				hfteditpane.copy();
			}
		});
		hfteditcopy.setToolTipText("Copy");
		hfteditcopy.setIcon(new ImageIcon(hftedit.class.getResource("images/edit_copy.png")));
		toolBar.add(hfteditcopy);
		
		hfteditcut = new JButton("Cut");
		hfteditcut.setVerticalTextPosition(SwingConstants.BOTTOM);
		hfteditcut.setHorizontalTextPosition(SwingConstants.CENTER);
		hfteditcut.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				hfteditpane.cut();
			}
		});
		hfteditcut.setToolTipText("Cut");
		hfteditcut.setIcon(new ImageIcon(hftedit.class.getResource("images/edit_cut.png")));
		toolBar.add(hfteditcut);
		
		hfteditpaste = new JButton("Paste");
		hfteditpaste.setHorizontalTextPosition(SwingConstants.CENTER);
		hfteditpaste.setVerticalTextPosition(SwingConstants.BOTTOM);
		hfteditpaste.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				hfteditpane.paste();
				hfteditpane.getHighlighter().removeAllHighlights();
				}
		});
		hfteditpaste.setToolTipText("Paste");
		hfteditpaste.setIcon(new ImageIcon(hftedit.class.getResource("images/edit_paste.png")));
		toolBar.add(hfteditpaste);
		
		hfteditundo = new JButton("Undo");
		hfteditundo.setEnabled(false);
		hfteditundo.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent arg0) {
				 try {
                     if (undo.canUndo()) {
                         undo.undo();
                     }
                 } catch (CannotUndoException e) {
                     e.printStackTrace();
                 }
			}
		});
		hfteditundo.setVerticalTextPosition(SwingConstants.BOTTOM);
		hfteditundo.setHorizontalTextPosition(SwingConstants.CENTER);
		hfteditundo.setToolTipText("Undo");
		hfteditundo.setIcon(new ImageIcon(hftedit.class.getResource("images/edit_undo.png")));
		toolBar.add(hfteditundo);
		
		hfteditredo = new JButton("Redo");
		hfteditredo.setEnabled(false);
		hfteditredo.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				try {
                    if (undo.canRedo()) {
                        undo.redo();
                    }
                } catch (CannotRedoException ce) {
                    ce.printStackTrace();
                }
			}
		});
		hfteditredo.setHorizontalTextPosition(SwingConstants.CENTER);
		hfteditredo.setVerticalTextPosition(SwingConstants.BOTTOM);
		hfteditredo.setToolTipText("Redo");
		hfteditredo.setIcon(new ImageIcon(hftedit.class.getResource("images/edit_redo.png")));
		toolBar.add(hfteditredo);
		
		hfteditcncl = new JButton("Cancel");
		hfteditcncl.setVerticalTextPosition(SwingConstants.BOTTOM);
		hfteditcncl.setHorizontalTextPosition(SwingConstants.CENTER);
		hfteditcncl.setToolTipText("Cancel changes and exit");
		hfteditcncl.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent arg0) {
				dispose();
			}
		});
		hfteditcncl.setIcon(new ImageIcon(hftedit.class.getResource("images/dlgcan.png")));
		toolBar.add(hfteditcncl);
		//Check if file is local or remote
		if (d.getfl() == "local"){
			// its a local file
	      try
	      {
	    	 String stuff = d.getsel(); 
	         FileInputStream fileIn =
	                          new FileInputStream(d.getsel());
	         hfteditpane.read(fileIn, null);
	         fileIn.close();
	         hfteditpane.invalidate();
	      }catch(IOException i)
	      {
	    	  System.out.println("File "+d.getsel()+" was not found.");
	    	  return;
	      }

		}else{
		// its a remote file
			try {
				InputStream is = f.retrieveFileStream(d.getsel());
				System.out.println("getsel is "+d.getsel());
				hfteditpane.read(is, null);
				is.close();
				} catch (IOException e1) {
				e1.printStackTrace();
			}
		}
		hfteditpane.getDocument().addUndoableEditListener((UndoableEditListener) this);
	}
	
	 public void undoableEditHappened(UndoableEditEvent evt) {
	        if (evt.getEdit() instanceof AbstractDocument.DefaultDocumentEvent) {
	        	hfteditundo.setEnabled(true);
	        	hfteditredo.setEnabled(true);
	            if(lastEdit == null || !lastEdit.addEdit(evt.getEdit())) {
	                if (lastEdit != null)
	                    lastEdit.end();
	                lastEdit = new TypingEdit();
	                lastEdit.addEdit(evt.getEdit());
	                undo.addEdit(lastEdit);
	            }
	        } else {
	            undo.addEdit(evt.getEdit());
	        }
	 }

	

	//String origfile = JHFSeditpane.getText();
	private class findListener implements ActionListener {

		@Override
		public void actionPerformed(ActionEvent e) {
			if (e.getSource()== hftfinder.getFindnxtbtn()){
				String word = hftfinder.getFindword().getText();
				WordSearcher searcher = new WordSearcher(hfteditpane);
				// flags are for : forward search, find all, and replace. 
				searcher.search(word, true, false, false);
				}
			if (e.getSource()==hftfinder.getFindallbtn()){
				String word = hftfinder.getFindword().getText();
				WordSearcher searcher = new WordSearcher(hfteditpane);
				searcher.search(word, true, true, false);
			}
			if (e.getSource()==hftfinder.getFindprevbtn()){
				String word = hftfinder.getFindword().getText();
				WordSearcher searcher = new WordSearcher(hfteditpane);
				searcher.search(word, false, false, false);
			}
			if (e.getSource()==hftfinder.getRepbtn()){
				String word = hftfinder.getFindword().getText();
				WordSearcher searcher = new WordSearcher(hfteditpane);
				searcher.search(word, true, false, true);
			}
			if (e.getSource()==hftfinder.getRepallbtn()){
				String word = hftfinder.getFindword().getText();
				WordSearcher searcher = new WordSearcher(hfteditpane);
				searcher.search(word, true, true, true);
			}
			}
		
	}

	public static JEditorPane getJHFSeditpane() {
		return hfteditpane;
	}

	public JButton getJHFSeditsavebtn() {
		return hfteditsave;
	}
	public JButton getJHFSeditselallbtn() {
		return hfteditselall;
	}
	public JButton getJHFSeditcopybtn() {
		return hfteditcopy;
	}
	public JButton getJHFSeditcutbtn() {
		return hfteditcut;
	}
	public JButton getJHFSeditpastebtn() {
		return hfteditpaste;
	}
	public JButton getJHFSeditredobtn() {
		return hfteditredo;
	}
	public JButton getJHFSeditundobtn() {
		return hfteditundo;
	}

	public JButton getJHFSeditfindbtn() {
		return hfteditfind;
	}
	  public static String word;

	  public static Highlighter highlighter = new UnderlineHighlighter(null);
	  private static JScrollPane scrollPane;

	public static JScrollPane getScrollPane() {
		return scrollPane;
	}
	}

	// A simple class that searches for a word in
	// a document and highlights occurrences of that word

	class WordSearcher {
	  public WordSearcher(JEditorPane comp) {
	    this.comp = comp;
	    this.painter = (HighlightPainter) new UnderlineHighlighter.UnderlineHighlightPainter(
	        Color.red);
	  }
	    static int firstOffset = -1;
	    static int lastIndex = 0;
	    static int fcount = 0;
	    static boolean rpt;
	    static boolean foundone;
	    static Document d;
	  // Search for a word and return the offset of the
	  // first occurrence. Highlights are added for all
	  // occurrences found.
	  public static int search(String word,Boolean fwd, Boolean prpt, Boolean repl) {

	    Highlighter highlighter = comp.getHighlighter();
	    rpt = prpt;
	    // Remove any existing highlights for last word
	    Highlighter.Highlight[] highlights = highlighter.getHighlights();
	    for (int i = 0; i < highlights.length; i++) {
	      Highlighter.Highlight h = highlights[i];
	      if (h.getPainter() instanceof UnderlineHighlighter.UnderlineHighlightPainter) {
	        highlighter.removeHighlight(h);
	      }
	    }

	    if (word == null || word.equals("")) {
	      return -1;
	    }

	    // Look for the word we are given - insensitive search
	    String content = null;
	    try {
	      d = comp.getDocument();
	      content = d.getText(0, d.getLength()).toLowerCase();
	    } catch (BadLocationException e) {
	      // Cannot happen
	      return -1;
	    }
	    
	    word = word.toLowerCase();
	    int wordSize = word.length();
	    if(fwd && repl == false){ // Find Next was pressed
	    	lastIndex = hftedit.getJHFSeditpane().getCaretPosition();
	    	if (foundone == true){lastIndex += (wordSize+2);}
	    	while ((lastIndex = content.indexOf(word, lastIndex)) != -1) {
	    		dohighlighting(wordSize, highlighter, painter);
	    		hftedit.getJHFSeditpane().setCaretPosition(lastIndex);
	    		foundone = true;
	    		if (rpt == false){break;} // if rpt = false, find all was not pressed
	    		if (rpt == true){fcount +=1;}
	    	}
	    }
	    if(!fwd && repl == false){// Find Prev was pressed
	    	int cp = hftedit.getJHFSeditpane().getCaretPosition();
	    	if (cp > 0){lastIndex = cp;}
	    	if (foundone == true){lastIndex -= (wordSize+1);}
	    	else{lastIndex=content.length();}
	    	int finindex=content.indexOf(word, 0);
	    	while ((lastIndex = content.lastIndexOf(word, lastIndex)) > (finindex-wordSize) && lastIndex != -1) {
	    		dohighlighting(wordSize, highlighter, painter);
	    		hftedit.getJHFSeditpane().setCaretPosition(lastIndex);
	    		lastIndex -= wordSize;
	    		if (lastIndex != -1) {foundone = true;}
	    		hftedit.getJHFSeditpane().setCaretPosition(lastIndex-(wordSize+1));
	    		if (rpt == false){break;}
	    	}	    	
	    }
	    if (fwd == true && repl == false && lastIndex == -1){ // Find All was pressed
	    	if (foundone == true && rpt == false){
JOptionPane.showMessageDialog(hftedit.getJHFSeditpane(), "No further matching text was found.","HFS Tools",JOptionPane.INFORMATION_MESSAGE);
	    	}else if (foundone == false){
JOptionPane.showMessageDialog(hftedit.getJHFSeditpane(), "No matching text was found.","HFS Tools",JOptionPane.INFORMATION_MESSAGE);
	    	}
	    
	    }
	    if (fwd == false && repl == false && lastIndex == -1){ // Replace  All was pressed
	    	if (foundone == true){
JOptionPane.showMessageDialog(hftedit.getJHFSeditpane(), "No further matching text was found.","HFS Tools",JOptionPane.INFORMATION_MESSAGE);
	    	}else if (foundone == false)
	    	{
JOptionPane.showMessageDialog(hftedit.getJHFSeditpane(), "No matching text was found.","HFS Tools",JOptionPane.INFORMATION_MESSAGE);
	    	}
	    }
	    if (fwd && repl && rpt == false){ // Replace was pressed
	    	lastIndex = hftedit.getJHFSeditpane().getCaretPosition();
	    	if (foundone == true){lastIndex += (wordSize+2);}
	    	while ((lastIndex = content.indexOf(word, lastIndex)) != -1) {
	    		System.out.println("I would paste "+hftfinder.getRepword().getText()+" here");
	    		try {
					d.remove(lastIndex, wordSize);
					d.insertString(lastIndex, JHfstools.hftfinder.getRepword().getText(),null);
				} catch (BadLocationException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
	    		hftedit.getJHFSeditpane().setCaretPosition(lastIndex);
	    		foundone = true;
	    		if (rpt == false){break;}
	    	}	
	    }
	    if (fcount > 0){
JOptionPane.showMessageDialog(hftedit.getJHFSeditpane(), fcount+" occurances of "+word+" found.","HFS Tools",JOptionPane.INFORMATION_MESSAGE);
	    }
	    return firstOffset;
	  }
	    public static void dohighlighting(int wordSize, Highlighter highlighter,Highlighter.HighlightPainter painter ){
		      int endIndex = lastIndex + wordSize;
		      try {
		        highlighter.addHighlight(lastIndex, endIndex, painter);
		      //  if (rpt == false){break;}
		      } catch (BadLocationException e) {
		    	  e.printStackTrace();
		        // Nothing to do
		      }
		      if (firstOffset == -1) {
		        firstOffset = lastIndex;
		      }
		      lastIndex = endIndex;	
	    }
	  protected static JEditorPane comp;

	  protected static Highlighter.HighlightPainter painter;

	}

	class UnderlineHighlighter extends DefaultHighlighter {
	final Highlighter.HighlightPainter sharedPainter = new UnderlineHighlightPainter(
	     null);
			   // Painter used for this highlighter
	  public Highlighter.HighlightPainter painter;
	  public UnderlineHighlighter(Color c) {
	    painter = (c == null ? sharedPainter : new UnderlineHighlightPainter(c));
	  }

	  // Convenience method to add a highlight with
	  // the default painter.
	  public Object addHighlight(int p0, int p1) throws BadLocationException {
	    return addHighlight(p0, p1, painter);
	  }

	  public void setDrawsLayeredHighlights(boolean newValue) {
	    // Illegal if false - we only support layered highlights
	    if (newValue == false) {
	      throw new IllegalArgumentException(
	          "UnderlineHighlighter only draws layered highlights");
	    }
	    super.setDrawsLayeredHighlights(true);
	  }

	  // Painter for underlined highlights
	  public static class UnderlineHighlightPainter extends
	      LayeredHighlighter.LayerPainter {
	    public UnderlineHighlightPainter(Color c) {
	      color = c;
	    }

	    public void paint(Graphics g, int offs0, int offs1, Shape bounds,
	        JTextComponent c) {
	      // Do nothing: this method will never be called
	    }

	    public Shape paintLayer(Graphics g, int offs0, int offs1, Shape bounds,
	        JTextComponent c, View view) {
	      g.setColor(color == null ? c.getSelectionColor() : color);

	      Rectangle alloc = null;
	      if (offs0 == view.getStartOffset() && offs1 == view.getEndOffset()) {
	        if (bounds instanceof Rectangle) {
	          alloc = (Rectangle) bounds;
	        } else {
	          alloc = bounds.getBounds();
	        }
	      } else {
	        try {
	          Shape shape = view.modelToView(offs0,
	              Position.Bias.Forward, offs1,
	              Position.Bias.Backward, bounds);
	          alloc = (shape instanceof Rectangle) ? (Rectangle) shape
	              : shape.getBounds();
	        } catch (BadLocationException e) {
	          return null;
	        }
	      }

	      FontMetrics fm = c.getFontMetrics(c.getFont());
	      int baseline = alloc.y + alloc.height - fm.getDescent() + 1;
	      g.drawLine(alloc.x, baseline, alloc.x + alloc.width, baseline);
	      g.drawLine(alloc.x, baseline + 1, alloc.x + alloc.width,
	          baseline + 1);

	      return alloc;

	    }

		protected Color color; // The color for the underline

		  // Shared painter used for default highlighting
/*		  final Highlighter.HighlightPainter sharedPainter = new UnderlineHighlightPainter(
		      null);
		   // Painter used for this highlighter
		  public Highlighter.HighlightPainter painter;*/
		  }

}
	


